﻿using Core.Framework;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;

namespace Dashboard.Middlewares
{
    public class ClientPositionMiddlewares
    {
        const string baiduKey = "trVO46FyA9Ofbmq2oGAtCT0fMgLL38CB";
        private readonly RequestDelegate _next;
        private Dictionary<string, string> keyValuePairs = new Dictionary<string, string>();
        IHttpClientFactory httpClientFactory;

        public ClientPositionMiddlewares(RequestDelegate next, IHttpClientFactory httpClientFactory)
        {
            this._next = next ?? throw new ArgumentNullException(nameof(next));
            this.httpClientFactory = httpClientFactory;
        }

        public async Task Invoke(HttpContext context)
        {

            // 解决 nginx、docker等 获取ip问题
            var ip = context.Request.Headers["X-Forwarded-For"].FirstOrDefault();
            if (string.IsNullOrEmpty(ip))
            {
                ip = context.Connection.RemoteIpAddress.MapToIPv4().ToString();
            }

            try
            {
                if (!string.IsNullOrWhiteSpace(ip))
                {
                    if (!keyValuePairs.ContainsKey(ip))
                    {
                        var baiduUri = $"https://api.map.baidu.com/location/ip?ak={baiduKey}&ip={ip}&coor=bd09ll";
                        var result = await this.GetAsync(baiduUri);
                        if (!string.IsNullOrWhiteSpace(result))
                        {
                            var address = result.TryToEntity<Address>();
                            if (address.status == 0)
                            {
                                LoggerUtils.Write($"ip:{ip}, address:{address?.content?.address}", "address");
                                await this._next(context);
                                return;
                            }
                        }
                        keyValuePairs.Add(ip, result);
                    }
                }
            }
            catch (Exception ex)
            {
                LoggerUtils.Write(ex.Message);
            }

            await this._next(context);
        }

        class Address
        {
            public int status { get; set; }
            public AddressContent content { get; set; }
        }

        class AddressContent
        {
            public string address { get; set; }
            public AddressDetail address_detail { get; set; }
        }

        class AddressDetail
        {
            public string city { get; set; }
            public string province { get; set; }
        }

        public async Task<string> GetAsync(string url)
        {
            try
            {
                var result = await this.httpClientFactory.CreateClient().GetAsync(url);
                var value = await result.Content.ReadAsStringAsync();

                if (result.StatusCode != System.Net.HttpStatusCode.OK)
                {
                    throw new Exception(value);
                }

                return value;
            }
            catch (Exception ex)
            {
                LoggerUtils.Write("PostAsync", ex);
                throw ex;
            }
        }

    }
}
